package com.jasonchoi.elk.log4j2;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.nio.charset.Charset;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.Node;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.AbstractStringLayout;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.core.layout.PatternSelector;
import org.apache.logging.log4j.core.pattern.RegexReplacement;

@Plugin(name = "CostomJsonPatternLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
public class CostomJsonPatternLayout extends AbstractStringLayout {
  /**
   * 项目路径
   */
  private static String PROJECT_PATH;

  private PatternLayout patternLayout;

  private String appName;

  static {
    PROJECT_PATH = new File("").getAbsolutePath();
  }

  public CostomJsonPatternLayout(Configuration config, RegexReplacement replace, String eventPattern,
      PatternSelector patternSelector, Charset charset, boolean alwaysWriteExceptions,
      boolean noConsoleNoAnsi, String headerPattern, String footerPattern, String appName) {
    super(config, charset,
        PatternLayout.createSerializer(config, replace, headerPattern, null, patternSelector, alwaysWriteExceptions,
            noConsoleNoAnsi),
        PatternLayout.createSerializer(config, replace, footerPattern, null, patternSelector, alwaysWriteExceptions,
            noConsoleNoAnsi));

    this.appName = appName;
    this.patternLayout = PatternLayout.newBuilder()
                                      .withPattern(eventPattern)
                                      .withPatternSelector(patternSelector)
                                      .withConfiguration(config)
                                      .withRegexReplacement(replace)
                                      .withCharset(charset)
                                      .withAlwaysWriteExceptions(alwaysWriteExceptions)
                                      .withNoConsoleNoAnsi(noConsoleNoAnsi)
                                      .withHeader(headerPattern)
                                      .withFooter(footerPattern)
                                      .build();
  }

  @Override
  public String toSerializable(LogEvent event) {
    //在这里处理日志内容
    String message = patternLayout.toSerializable(event);
    String jsonStr = new JsonLoggerInfo(appName, message, event.getLevel().name(), event.getTimeMillis()).toString();
    return jsonStr + "\n";
  }

  @PluginFactory
  public static CostomJsonPatternLayout createLayout(
      @PluginAttribute(value = "pattern", defaultString = PatternLayout.DEFAULT_CONVERSION_PATTERN) final String pattern,
      @PluginElement("PatternSelector") final PatternSelector patternSelector,
      @PluginConfiguration final Configuration config,
      @PluginElement("Replace") final RegexReplacement replace,
      // LOG4J2-783 use platform default by default, so do not specify defaultString for charset
      @PluginAttribute(value = "charset") final Charset charset,
      @PluginAttribute(value = "alwaysWriteExceptions", defaultBoolean = true) final boolean alwaysWriteExceptions,
      @PluginAttribute(value = "noConsoleNoAnsi", defaultBoolean = false) final boolean noConsoleNoAnsi,
      @PluginAttribute("header") final String headerPattern,
      @PluginAttribute("footer") final String footerPattern,
      @PluginAttribute("appName") final String appName) {


    return new CostomJsonPatternLayout(config, replace, pattern, patternSelector, charset,
        alwaysWriteExceptions, noConsoleNoAnsi, headerPattern, footerPattern, appName);
  }

  /**
   * 输出的日志内容
   */
  public static class JsonLoggerInfo {
    /**
     * 项目名
     */
    private String appName;
    /**
     * 项目目录路径
     */
    private String projectPath;
    /**
     * 日志信息
     */
    private String message;
    /**
     * 日志级别
     */
    private String level;
    /**
     * 日志时间
     */
    private String time;

    public JsonLoggerInfo(String appName, String message, String level, long timeMillis) {
      this.appName = appName;
      this.projectPath = PROJECT_PATH;
      this.message = message;
      this.level = level;
      this.time = DateFormatUtils.format(timeMillis, "yyyy-MM-dd HH:mm:ss.SSS");
    }

    public String getAppName() {
      return appName;
    }

    public String getProjectPath() {
      return projectPath;
    }

    public String getMessage() {
      return message;
    }

    public String getLevel() {
      return level;
    }


    public String getTime() {
      return time;
    }

    @Override
    public String toString() {
      try {
        return new ObjectMapper().writeValueAsString(this);
      } catch (JsonProcessingException e) {
        e.printStackTrace();
      }
      return null;
    }
  }
}
